package com.hertz.appr.service;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.hertz.appr.cache.Cache;
import com.hertz.appr.cache.CacheFactory;
import com.hertz.appr.dao.IBaseDao;
import com.hertz.appr.pojo.db.Action;
import com.hertz.appr.pojo.db.Message;
/**
 * 提供默认命令 guess(\d)
 * @author hongzhe
 *
 */
public class ActionService {
	private static Logger log = Logger.getLogger(ActionService.class);
	
	private String idActionRegion = "action";
	private String tidProviderActionRegion = "tidProviderAction";
	
	private IBaseDao<Action, Long> actionDao;
	private MemberService memberService;
	private static List<String> id62HexLetters;
	private static int idHex = 62;
	private static Pattern p62Hex = Pattern.compile("[1-9a-zA-Z]?[0-9a-zA-Z]+");
	private CacheFactory cacheFactory;
	static{
		id62HexLetters = new ArrayList<String>();
		for(int i = 0; i<10; i++){
			id62HexLetters.add(String.valueOf(i));
		}
		for(byte i = 97; i < 123; i++){
			String lower = String.valueOf((char)i);
			String upper = lower.toUpperCase();
			id62HexLetters.add(lower);
			id62HexLetters.add(upper);
		}
	}
	
	public Action getAction(Message msg){
		if(msg != null)
			log.debug(msg);
		if(msg == null || StringUtils.isBlank(msg.getTid()) || StringUtils.isBlank(msg.getProvider())){
			log.debug("return null");
			return null;
		}
		log.debug("regTid=" + msg.getTid() + ";provider=" + msg.getProvider());
		String key = msg.getTid() + "-" + msg.getProvider();
		Cache cache = cacheFactory.buildCache(tidProviderActionRegion);
		Action action = (Action)cache.get(key);
		log.debug("get action from cache,key=" + key);
		if(action == null){
			log.debug("get action from db,key=" + key);
			String hql = "from Action as a where a.regTid=? and a.provider=?";
			List<Action> list = actionDao.find(hql, msg.getTid(),msg.getProvider());
			if(list == null || list.size() == 0){
				log.info("no action,return null");
				return null;
			}
			if(list.size() > 1){
				log.info("more actions,return null");
				return null;
			}
			action = list.get(0);
			if(action != null){
				cache.read(key);
				cache.put(key, action);
				log.debug("put action in cache,key=" + key);
			}else{
				log.info("action is null in db");
			}
		}
		return action;
	}
	
	public static String getActionId62Hex(Long id10Hex){
		long quotient = id10Hex / idHex;
		long mod = id10Hex % idHex;
		String value = id62HexLetters.get(Long.valueOf(mod).intValue());
		while(quotient >= idHex){
			mod = quotient % idHex;
			quotient = quotient / idHex;
			value = id62HexLetters.get(Long.valueOf(mod).intValue()) + value; 
		}
		if(quotient != 0)
			value = id62HexLetters.get(Long.valueOf(quotient).intValue()) + value;
		return value;
	}
	/**
	 * 
	 * @param str
	 * @return str不正确，返回-1
	 */
	public static long getActionId10Hex(String str){
		log.debug("62 hex id = " + str);
		Matcher m62Hex = p62Hex.matcher(str);
		long result = -1;
		if(m62Hex.matches()){
			result = 0;
			int j = 0;
			String temp = "";
			if(str.length() >= 1){
				for(int i = str.length() - 1; i >= 0; i--){
					temp = str.substring(i, i + 1);
					int index = id62HexLetters.indexOf(temp);
					result = Double.valueOf(Math.pow(idHex, j)).longValue() * index + result; 
					j++;
				}
			}
		}
		return result;
	}
	
	public void saveAction(Action action){
		if(action != null){
			actionDao.save(action);
			log.debug("save action 2 db: " + action.toString());
			flushCache(action, action.getId().toString(),idActionRegion);
		}
	}
	
	public void updateAction(Action action){
		if(action != null){
			actionDao.update(action);
			log.debug("update action 2 db");
			log.debug("save action 2 db: " + action.toString());
		}
	}

	public Action getAction(String aidStr){
		if(StringUtils.isEmpty(aidStr)){
			return null;
		}
		Long aid = getActionId10Hex(aidStr);
		if(aid > 0)
			return getAction(aid);
		else
			return null;
	}
	
	public List<Action> getActions(Short status){
		String hql = "from Action a where a.status=? order by createTime desc";
		List<Action> actionList = actionDao.find(hql, status);
		return actionList;
	}
	
	public List<Action> getActions(String provider,Short status){
		String hql = "from Action a where a.status=? and a.provider=?";
		List<Action> actionList = actionDao.find(hql, status,provider);
		return actionList;
	}
	
	public void flushCache(Action action, String key,String region){
		Cache cache = cacheFactory.buildCache(region);
		Action a = (Action)cache.get(key);
		if(a == null){
			cache.put(key, action);
			log.debug("put action 2 cache");
		}else{
			cache.remove(action.getId());
			cache.put(key, action);
			log.debug("update action 2 cache");
		}
	}
	
	public Action getAction(Long aid){
		Cache cache = cacheFactory.buildCache(idActionRegion);
		Action a = (Action)cache.get(aid.toString());
		log.debug("get action from cache =" + a);
		if(a != null)
			return a;
		else{
			a = actionDao.getById(aid);
			log.debug("get action from db =" + a);
			if(a != null){
				flushCache(a, aid.toString(),idActionRegion);
			}
			return a;
		}
	}
	
	public IBaseDao<Action, Long> getActionDao() {
		return actionDao;
	}

	public void setActionDao(IBaseDao<Action, Long> actionDao) {
		this.actionDao = actionDao;
	}

	public MemberService getMemberService() {
		return memberService;
	}

	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}
	public List<String> getId62HexLetters() {
		return id62HexLetters;
	}
	public void setId62HexLetters(List<String> id62HexLetters) {
		this.id62HexLetters = id62HexLetters;
	}
	public int getIdHex() {
		return idHex;
	}
	public void setIdHex(int idHex) {
		this.idHex = idHex;
	}

	public CacheFactory getCacheFactory() {
		return cacheFactory;
	}

	public void setCacheFactory(CacheFactory cacheFactory) {
		this.cacheFactory = cacheFactory;
	}
}
